﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using System.Xml;
using System.Xml.Serialization;

namespace SusyGame_Model
{
    [Serializable]
    public class Player
    {
        //Atributos
        private String nickname;
        private int score;
        private int points;
        private List<Defender> defenders = new List<Defender>();
        private Map map;
        private string newDefenderType;

        [NonSerialized]
        private MouseState mouseState;
        [NonSerialized]
        private MouseState oldState;
        [NonSerialized]
        private Texture2D[] defenderTextures;
        [NonSerialized]
        private Texture2D weaponTexture;
        [NonSerialized]
        [XmlIgnore]
        private int cellX;
        private int cellY;
        private int tileX;
        private int tileY;
        
        //Propiedades
        public List<Defender> Defenders
        {
            get { return defenders; }
            set { defenders = value; }
        }
        public Map Map
        {
            get { return map; }
            set { map = value; }
        }
        public string NewDefenderType
        {
            set { newDefenderType = value; }
        }
        public String Nickname
        {
            get { return nickname; }
            set { nickname = value; }
        }

        public int Score
        {
            get { return score; }
            set { score = value; }
        }
        
        public int Points
        {
            get { return points; }
            set { points = value; }
        }

        public MouseState MouseState
        {
            get { return mouseState; }
            set { mouseState = value; }
        }

        public Texture2D[] DefenderTextures
        {
            get { return defenderTextures; }
            set { defenderTextures = value; }
        }

        public Texture2D WeaponTexture
        {
            get { return weaponTexture; }
            set { weaponTexture = value; }
        }

        public MouseState OldState
        {
            get { return oldState; }
            set { oldState = value; }
        }

        public Player()
        {
        }

        public Player(Map map, Texture2D[] defenderTextures, Texture2D weaponTexture)
        {
            this.map = map;
            this.defenderTextures = defenderTextures;
            this.weaponTexture = weaponTexture;
            this.points = 100;
        }      

        public void Update(GameTime gameTime, List<Enemy> enemies)
        {
            MouseState = Mouse.GetState();

            cellX = (int)(MouseState.X / 150); 
            cellY = (int)(MouseState.Y / 80);

            tileX = cellX * 150; 
            tileY = cellY * 80;

            if (MouseState.LeftButton == ButtonState.Released && OldState.LeftButton == ButtonState.Pressed)
            {
                if (string.IsNullOrEmpty(newDefenderType) == false)
                {
                    AddDefender();
                }
            }

            //AQUI LLAMO AL METODO QUE VERIFICA SI MIS DEFENSORES HAN SIDO PASADOS POR LOS ENEMIGOS.
            areDefendersDead();

            foreach (Defender defender in Defenders)
            {
                if (defender.HasTarget == false)
                {
                    defender.GetClosestEnemy(enemies);
                }

                defender.Update(gameTime);
            }

            OldState = MouseState;
        }

        private bool IsCellClear(int tipo)
        {
            bool inBounds = cellX >= 0 && cellY >= 0 &&
                cellX < Map.Ancho && cellY < Map.Alto;

            bool spaceClear = true;

            foreach (Defender defender in Defenders) 
            {
                spaceClear = (defender.Position != new Vector2(tileX, tileY));

                if (!spaceClear)
                    break;
            }

            bool onPath = (((Map.GetIndex(cellX, cellY) == 1) && tipo == 1) || ((Map.GetIndex(cellX, cellY) == 0) && tipo == 2));

            return inBounds && spaceClear && onPath; 
        }

        //METODO QUE VERIFICA TODA MI LISTA DE DEFENSORES PARA VER SI ALGUNO A SIDO PASADO POR ALGUN ENEMIGO, EN ESE CASO LO ELIMINO DE LA LISTA
        private void areDefendersDead()
        {
            for (int i = 0; i < Defenders.Count; i++)
            {
                Defender defenderAux = Defenders[i];

                if (defenderAux.HaveCrashed())
                {
                    Defenders.Remove(defenderAux);
                }
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (Defender defender in Defenders)
            {
                defender.Draw(spriteBatch);
            }
        }

        public void AddDefender()
        {
            Defender defenderToAdd = null;

            switch (newDefenderType)
            {
                case "Arrow Defender":
                    {
                        defenderToAdd = new ArrowDefender(defenderTextures[0],weaponTexture, new Vector2(tileX, tileY));
                        break;
                    }
                case "Spike Defender":
                    {
                        defenderToAdd = new SpikeDefender(defenderTextures[1], weaponTexture, new Vector2(tileX, tileY));
                        break;
                    }
                case "Aqua Defender":
                    {
                        defenderToAdd = new AquaDefender(defenderTextures[2], weaponTexture, new Vector2(tileX, tileY));
                        break;
                    }
            }

            // Only add the tower if there is a space and if the player can afford it.
            if (IsCellClear(defenderToAdd.Tipo) == true && defenderToAdd.Price <= points)
            {
                defenders.Add(defenderToAdd);
                points -= defenderToAdd.Price;

                // Reset the newTowerType field.
                newDefenderType = string.Empty;
            }
        }
    }
}